package com.qipay.core.utils;


import com.qipay.baas.model.Menu;
import com.qipay.core.exception.AppException;
import com.qipay.core.exception.SystemException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 通过Util
 * 后续有通用的Util都往这里面加
 *
 * @author 郭明粳
 */
public class CommUtil {
    private static Logger LOGGER = LoggerFactory.getLogger(CommUtil.class);

    /**
     * 代权限的生成菜单里面的li标签
     *
     * @param menus
     * @param contextPath
     */
    public static String renderMenu(List<Menu> menus, String contextPath, String userName) {
        StringBuffer h = new StringBuffer("");
        menus.stream().filter(pm -> CommUtil.isEmpty(pm.getSuperiorId())).forEach(m -> {
                    h.append("<li class=\"treeview\">");
                    h.append("<a href=\"#\">");
                    h.append("<i class=\"fa fa-dashboard\"></i> <span>").append(m.getMenuName()).append("</span>");
                    h.append("<span class=\"pull-right-container\">");
                    h.append("<i class=\"fa fa-angle-left pull-right\"></i>");
                    h.append("</span>");
                    h.append("</a>");
                    h.append("<ul class=\"treeview-menu\">");
                    menus.stream().filter(cm -> CommUtil.equalsNumber(m.getMenuId(), cm.getSuperiorId())).forEach(cm -> {
                        String uri = cm.getMenuUri().replaceAll("=userName=", userName);;
                        h.append("<li><a href=\"").append(contextPath).append(uri).append("\"><i class=\"fa fa-circle-o\"></i>")
                                .append(cm.getMenuName())
                                .append("</a></li>");
                    });
                    h.append("</ul>");
                    h.append("</li>");
                }
        );
        return h.toString();
    }

    /**
     * 判断Object是否为null
     */
    public static boolean isNull(Object oValue) {
        return oValue == null ? true : false;
    }


    /**
     * 判断对象内容是否为空
     * 对象等于null 为空
     * 对象类型支持 数组、字符串、
     *
     * @param obj
     * @return
     */
    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }
        if (obj.getClass().isArray()) {
            return Array.getLength(obj) == 0;
        } else if (obj instanceof String) {
            return ((String) obj).trim().length() == 0;
        } else if (obj instanceof CharSequence) {
            return ((CharSequence) obj).length() == 0;
        } else if (obj instanceof Collection) {
            return ((Collection) obj).isEmpty();
        } else if (obj instanceof Map) {
            return ((Map) obj).isEmpty();
        } else if (obj instanceof Set) {
            return ((Set) obj).isEmpty();
        } else {
            return false;
        }
    }

    /**
     * 判断是否不为空
     */
    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }


    /**
     * 判断两个String是否相等,如果是字符,比较是否相同,如果是数字,比较是否相等
     *
     * @param aStr String
     * @param bStr String
     * @return boolean
     */
    public static boolean equalsNumberOrChar(String aStr, String bStr) {
        boolean isSame = false;
        aStr = toString(aStr);
        bStr = toString(bStr);
        if ((isEmpty(aStr)) && isEmpty(bStr)) {
            isSame = true;
        } else if ((isEmpty(aStr)) || (isEmpty(bStr))) {
            isSame = false;
        } else if (aStr.equals(bStr)) {
            isSame = true;
        } else if (isNumber(aStr) && isNumber(bStr)) {
            BigDecimal aNum = new BigDecimal(aStr);
            BigDecimal bNum = new BigDecimal(bStr);

            if (aNum.compareTo(bNum) == 0) {
                isSame = true;
            }
        }
        return isSame;
    }

    /**
     * Return string length after trim
     */
    public static int strLen(String sValue) {
        return isNull(sValue) ? 0 : sValue.trim().length();
    }

    /**
     * 判断是否为整数
     */
    public static boolean isInt(String sValue) {
        if (isEmpty(sValue))
            return false;
        try {
            Integer.parseInt(sValue);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断是否为长整数
     */
    public static boolean isLong(String sValue) {
        if (isEmpty(sValue))
            return false;
        try {
            Long.parseLong(sValue);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断是否为数字
     */
    public static boolean isNumber(String sValue) {
        if (isEmpty(sValue))
            return false;
        try {
            Double.parseDouble(sValue);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Convert string to string after trim
     */
    public static String toString(String sValue) {
        return isNull(sValue) ? "" : sValue.trim();
    }

    /**
     * 判断两个String是否相等,如果是字符,比较是否相同,如果是数字,比较是否相等
     *
     * @param aStr String
     * @param bStr String
     * @return boolean
     */
    public static boolean equalsString(String aStr, String bStr) {
        boolean isSame = false;
        aStr = toString(aStr);
        bStr = toString(bStr);
        if ((isEmpty(aStr)) && isEmpty(bStr)) {
            isSame = true;
        } else if ((isEmpty(aStr)) || (isEmpty(bStr))) {
            isSame = false;
        } else if (aStr.equals(bStr)) {
            isSame = true;
        }
        return isSame;
    }

    /**
     * 判断两个数字是否相等,可以是Long、long、Float、float、int、Integer、double、Double、Byte、byte
     *
     * @param aNum
     * @param bNum
     * @return boolean
     */
    public static boolean equalsNumber(Number aNum, Number bNum) {
        if (aNum == bNum) {
            return true;
        } else if (aNum == null || bNum == null) {
            return false;
        } else {
            return aNum.equals(bNum);
        }
    }


    /**
     * 判断是否前端页面临时ID
     *
     * @param id
     * @return
     */
    public static boolean isPageTempID(long id) {
        return isPageTempID(String.valueOf(id));
    }

    /**
     * 判断是否前端页面临时ID
     * 前端页面是9个9加8位随机数为临时ID
     *
     * @param id
     * @return
     */
    public static boolean isPageTempID(String id) {
        if (id.length() == 17 && (id.startsWith("999999999"))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 将一个数字转换成固定位数的字符串，不够补0
     *
     * @param @param  intstr 初始数据
     * @param @param  index  长度
     * @param @param  cover  补位的字
     * @param @return
     * @return String
     */
    public static String toStringZeroByInt(long intstr, long index, String cover) {
        StringBuilder str = new StringBuilder();
        str.append(intstr);
        if (str.length() >= index) {
            return str.toString();
        }
        StringBuilder beforeStr = new StringBuilder();
        for (int i = str.length(); i < index; i++) {
            beforeStr.append(cover);
        }
        return StringUtils.join(new String[]{beforeStr.toString(), str.toString()});
    }

    /**
     * 将输入流转换字符串
     *
     * @param is
     * @return
     * @throws IOException
     */
    public static String readInputStreamToString(InputStream is, String charsetName)
            throws IOException {
        InputStreamReader isr = new InputStreamReader(is, charsetName);
        return readerToString(isr);
    }

    /**
     * 将输入流转换字符串
     *
     * @param isr
     * @return
     * @throws IOException
     */
    public static String readerToString(Reader isr)
            throws IOException {
        StringBuffer strBF = new StringBuffer();
        char[] readbf = new char[8192];
        int readSize = 0;
        try {
            while ((readSize = isr.read(readbf)) > 0) {
                strBF.append(readbf, 0, readSize);
            }
        } finally {
            if (isr != null) {
                isr.close();
            }
        }
        return strBF.toString();
    }


    /**
     * 把字串转换为日期
     *
     * @param sdate  字串形式的日期
     * @param format 字串格式
     * @return 转换为日期类型
     */
    public static Date str2Date(String sdate, String format) {
        try {
            if (sdate == null || sdate != null && sdate.trim().length() == 0)
                return null;
            SimpleDateFormat df = new SimpleDateFormat(format);
            return df.parse(sdate);
        } catch (ParseException e) {
            throw new SystemException("字符转日期异常", e, "请检测输入的值是否正确");
        }
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date getCurDateTime() {
        return new Date();
    }

    /**
     * 获取当前时间
     * yyyy-MM-dd HH:mm:ss
     *
     * @return
     */
    public static String getCurDateTimeStr() {
        return date2Str(new Date());
    }

    /**
     * 把时间转换为字串 格式：yyyy-MM-dd HH:mm:ss
     *
     * @param date 待转换的时间
     * @return
     */
    public static String date2Str(Date date) {
        String format = "yyyy-MM-dd HH:mm:ss";
        return date2Str(date, format);
    }

    /**
     * 把时间转换为字串 格式：yyyy-MM-dd
     *
     * @param date 待转换的时间
     * @return
     */
    public static String date2StrNotTime(Date date) {
        String format = "yyyy-MM-dd";
        return date2Str(date, format);
    }

    /**
     * 把时间转换为字串
     *
     * @param date   待转换的时间
     * @param format 转换格式
     * @return
     */
    public static String date2Str(Date date, String format) {
        SimpleDateFormat df = new SimpleDateFormat(format);
        return df.format(date);
    }

    /**
     * 获取当前日期：yyyy-MM-dd
     *
     * @return
     */
    public static Date getCurDate() {
        return str2Date(date2Str(new Date(), "yyyy-MM-dd"), "yyyy-MM-dd");
    }


    /**
     * 获取当前年月 样式为yyyy-MM
     *
     * @return
     */
    public static String getCurYM() {
        return date2Str(new Date(), "yyyy-MM");
    }

    /**
     * 获取当前年度
     *
     * @return
     */
    public static String getCurYear() {
        return date2Str(new Date(), "yyyy");
    }

    /**
     * 获取当前年月日 样式为yyMMdd
     *
     * @return
     */
    public static String getCurYMD() {
        return date2Str(new Date(), "yyMMdd");
    }

    /**
     * 获取当前年月日 样式为yyyyMMdd
     *
     * @return
     */
    public static String getCurYyyyMD() {
        return date2Str(new Date(), "yyyyMMdd");
    }

    /**
     * 根据增加or减少的时间得到新的日期
     *
     * @param curDate   当前日期
     * @param field     需操作的'年'or'月'or'日'
     * @param addNumber 增加or减少的时间
     * @return
     */
    public static Date dateAdd(Date curDate, int field, int addNumber) {
        GregorianCalendar curGc = new GregorianCalendar();
        curGc.setTime(curDate);
        curGc.add(field, addNumber);
        return curGc.getTime();
    }


    /**
     * 根据增加or减少的天数
     *
     * @param curDate   当前日期
     * @param addNumber 增加or减少的天数
     * @return
     */
    public static Date dateAdd(Date curDate, int addNumber) {
        GregorianCalendar curGc = new GregorianCalendar();
        curGc.setTime(curDate);
        curGc.add(GregorianCalendar.DATE, addNumber);
        return curGc.getTime();
    }


    /**
     * @param date
     * @param addNumber
     * @return
     * @throws Exception
     */
    public static Date monthAdd(Date date, int addNumber) {
        return dateAdd(date, Calendar.MONTH, addNumber);
    }

    /**
     * 得到二个日期间隔
     *
     * @param dateBefore 开始日期
     * @param dateAfter  结束日期
     * @param field      间隔类型 (eg. Calendar.Month Calendar.Year)
     * @param amount     间隔数
     * @return 例：
     * getDateInterval(dateBefore,dateAfter,Calendar.Month,1),返回二个日期之间的月份。
     */
    public static int getDateInterval(Date dateBefore, Date dateAfter,
                                      int field, int amount) {
        int interval = 0;
        Calendar cb = new GregorianCalendar();
        Calendar da = new GregorianCalendar();
        cb.setTime(dateBefore);
        da.setTime(dateAfter);
        da.add(field, 1);
        for (Calendar c = cb; c.before(da); c.add(field, amount)) {
            interval++;
        }
        return interval;
    }

    /**
     * 得到两个日期之前的天数
     *
     * @param beginDate String 开始日期 格式:yyyy-MM-dd
     * @param endDate   String 结束日期 格式:yyyy-MM-dd
     * @return int
     */
    public static int getDateInterval(Date beginDate, Date endDate) {
        return getDateInterval(beginDate, endDate, Calendar.DATE, 1);
    }

    /**
     * 两个日期的间隔月份
     *
     * @param dateBefore
     * @param dateAfter
     * @return
     */
    public static int getMonthInterval(Date dateBefore, Date dateAfter) {
        return getDateInterval(dateBefore, dateAfter, Calendar.MONTH, 1);
    }


    /**
     * 字段名称转换成驼峰命名
     */
    public static String columnToProperty(String column) {
        StringBuilder result = new StringBuilder();
        // 快速检查
        if (column == null || column.isEmpty()) {
            // 没必要转换
            return "";
        } else if (!column.contains("_")) {
            // 都是大写字母的时候才转换成驼峰命名法，如果是大小写混写并且没有“_”已经是驼峰命名法不再转换
            if (CommUtil.equalsString(column.toUpperCase(), column)) {
                return column.toLowerCase();
            } else {
                return column;
            }
        } else {
            // 用下划线将原始字符串分割
            String[] columns = column.split("_");
            for (String columnSplit : columns) {
                // 跳过原始字符串中开头、结尾的下换线或双重下划线
                if (columnSplit.isEmpty()) {
                    continue;
                }
                // 处理真正的驼峰片段
                if (result.length() == 0) {
                    // 第一个驼峰片段，全部字母都小写
                    result.append(columnSplit.toLowerCase());
                } else {
                    // 其他的驼峰片段，首字母大写
                    result.append(columnSplit.substring(0, 1).toUpperCase()).append(columnSplit.substring(1).toLowerCase());
                }
            }
            return result.toString();
        }

    }

    /**
     * 驼峰Bean属性转换成列名称
     */
    public static String propertyToColumn(String property) {
        if (isEmpty(property)) {
            return "".toUpperCase();
        }
        char[] propertyArray = property.toCharArray();
        StringBuffer rs = new StringBuffer();
        for (char c : propertyArray) {
            if (c >= 'A' && c <= 'Z') {
//                Character.toUpperCase()
                rs.append('_');
                rs.append(Character.toUpperCase(c));
            } else {
                rs.append(Character.toUpperCase(c));
            }
        }
        return rs.toString();
    }


    /**
     * 获取唯一的uuid(32位)
     *
     * @return
     */
    public static String getUUID() {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return uuid;
    }

    /**
     * 将输入流转换字符串
     *
     * @param is
     * @return
     * @throws IOException
     */
    public static String readInputStreamToString(InputStream is)
            throws IOException {

        return readInputStreamToString(is, Charset.defaultCharset().name());
    }

    /**
     * 时间查询-开始时间转化YY-MM-DD HH-MM-SS date类型
     *
     * @param startTime
     * @return
     */
    public static Date getStartDateTime(Date startTime) {
        SimpleDateFormat formatterStr = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatterDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTimeStr = getStartTime(formatterStr.format(startTime));
        try {
            startTime = formatterDate.parse(startTimeStr);
        } catch (ParseException e) {
            throw new SystemException("时间String转成date类型出错", e, "请联系管理员处理");
        }
        return startTime;
    }

    /**
     * 时间查询-结束时间转化YY-MM-DD HH-MM-SS  date类型
     *
     * @param endTime
     * @return
     */
    public static Date getEndDateTime(Date endTime) {
        SimpleDateFormat formatterStr = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatterDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String endTimeStr = getEndTime(formatterStr.format(endTime));
        try {
            endTime = formatterDate.parse(endTimeStr);
        } catch (ParseException e) {
            throw new SystemException("时间String转成date类型出错", e, "请联系管理员处理");
        }
        return endTime;
    }

    /**
     * 时间查询-开始时间转化YY-MM-DD HH-MM-SS
     *
     * @param startTime
     * @return
     */
    public static String getStartTime(String startTime) {
        StringBuilder startStr = new StringBuilder(startTime);
        startStr.append(" 00:00:00");
        startTime = startStr.toString();
        return startTime;
    }

    /**
     * 时间查询-开始时间转化YY-MM-DD HH-MM-SS  输入date型返回date型
     *
     * @param startTime
     * @return
     */
    public static Date getStartTime(Date startTime) {
        String date2Str = CommUtil.date2Str(startTime, "yyyy-MM-dd");
        String time = CommUtil.getStartTime(date2Str);
        startTime = CommUtil.str2Date(time, "yyyy-MM-dd HH:mm:ss");
        return startTime;
    }

    /**
     * 时间查询-结束时间转化YY-MM-DD HH-MM-SS
     *
     * @param endTime
     * @return
     */
    public static String getEndTime(String endTime) {
        StringBuilder endStr = new StringBuilder(endTime);
        endStr.append(" 23:59:59");
        endTime = endStr.toString();
        return endTime;
    }

    /**
     * 时间查询-结束时间转化YY-MM-DD HH-MM-SS 输入date型返回date型
     *
     * @param endTime
     * @return endTime
     */
    public static Date getEndTime(Date endTime) {
        String date2Str = CommUtil.date2Str(endTime, "yyyy-MM-dd");
        String time = CommUtil.getEndTime(date2Str);
        endTime = CommUtil.str2Date(time, "yyyy-MM-dd HH:mm:ss");
        return endTime;
    }

    /**
     * 比较两个string型的时间
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static int comparaDate(String startDate, String endDate) {
        int compara = 0;
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date startDateDate = formatter.parse(startDate);
            Date endDateDate = formatter.parse(endDate);
            compara = endDateDate.compareTo(startDateDate);
        } catch (ParseException e) {
            throw new SystemException("时间String转成date类型出错", e, "请联系管理员处理");
        }

        return compara;
    }

    /**
     * 比较两个date类型的时间
     *
     * @param startDate
     * @param endDate
     * @return startDate>endDate返回-1
     * startDate<endDate返回1
     * startDate=endDate返回0
     */
    public static int comparaDate(Date startDate, Date endDate) {
        int compara = 0;
        if (isNull(startDate) || isNull(endDate)) {
            throw new SystemException("比较时间出错", "传入的时间不能为空", "请重新传入要比较的时间");
        } else {
            compara = endDate.compareTo(startDate);
            return compara;
        }
    }

    /**
     * 时间转换：yyyy-MM-dd
     *
     * @param date
     * @return
     */
    public static Date date2DateNotTime(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            String s = sdf.format(date);
            date = sdf.parse(s);
        } catch (ParseException e) {
            throw new SystemException("时间String转成date类型出错", e, "请联系管理员处理");
        }
        return date;
    }

    /**
     * byte转换成Base64
     *
     * @param byteArray
     * @return
     */
    public static String byteToBase64String(final byte[] byteArray) {
        return Base64.encodeBase64String(byteArray);
    }

    /**
     * Base64 String 转换成byte[]
     *
     * @param decodeBase64
     * @return
     */
    public static byte[] base64StringToByte(final String decodeBase64) {
        return Base64.decodeBase64(decodeBase64);
    }

    /**
     * 整型转换成Boolean型
     *
     * @param i
     * @return
     */
    public static Boolean stringToBoolean(String i) {
        if (CommUtil.equalsString("true", i) || CommUtil.equalsString("1", i)) {
            return true;
        } else if (CommUtil.equalsString("false", i) || CommUtil.equalsString("0", i)) {
            return false;
        } else {
            throw new SystemException("String转换成Boolean错误", "字符串" + i + "不能转成Boolean型", "请检测数据！");
        }
    }


    /**
     * Boolean型转换成整型
     *
     * @param b
     * @return
     */
    public static String booleanToIntStr(Boolean b) {
        if (b) {
            return "1";
        } else {
            return "0";
        }
    }

    /**
     * 是否基本数据类型或者基本数据类型的包装类
     */
    public static boolean isPrimitiveOrPrimitiveWrapper(Class<?> objectClass) {
        return objectClass.isPrimitive() ||
                (objectClass.isAssignableFrom(Byte.class) || objectClass.isAssignableFrom(Short.class) ||
                        objectClass.isAssignableFrom(Integer.class) || objectClass.isAssignableFrom(Long.class) ||
                        objectClass.isAssignableFrom(Double.class) || objectClass.isAssignableFrom(Float.class) ||
                        objectClass.isAssignableFrom(Character.class) || objectClass.isAssignableFrom(Boolean.class)) ||
                objectClass.isAssignableFrom(String.class) || objectClass.isAssignableFrom(BigDecimal.class);
    }

    /**
     * 字符串截取
     * 字符串的字节长度小于需要截取的长度，返回原字符串
     * 兼容中英文同时存在的字符串
     * 注：中文在oracle中占3个字节（UTF-8编码）
     *
     * @param str     需要截取的字符串
     * @param curSize 需要截取的长度
     * @return
     */
    public static String cutStrByU8(String str, int curSize) {
        if (CommUtil.isEmpty(str)) {
            throw new AppException("字符串截取错误", "传入的字符串为空", "请重新操作");
        }
        int count = 0;
        StringBuffer stringBuffer = new StringBuffer();
        try {
            if (str.getBytes("UTF-8").length > curSize) {
                char[] chars = str.toCharArray();
                for (char c : chars) {
                    if (count >= curSize) {
                        break;
                    }
                    if (isChinese(c)) { //判断是否为汉字
                        count += 3;
                        if (count >= curSize) {
                            break;
                        }
                    } else {
                        count++;
                    }
                    stringBuffer.append(c);
                }
            } else {
                return str;
            }
        } catch (UnsupportedEncodingException e) {
            throw new SystemException("获取字符长度失败", e, "请联系管理员");
        }
        return stringBuffer.toString();
    }

    /**
     * 字符串截取
     * 字符串的字节长度小于需要截取的长度，返回原字符串
     * 兼容中英文同时存在的字符串
     * 注：中文在oracle中占3个字节（UTF-8编码）
     *
     * @param str     需要截取的字符串
     * @param curSize 需要截取的长度
     * @return
     */
    public static String cutStr(String str, int curSize) {
        if (CommUtil.isEmpty(str)) {
            throw new AppException("字符串截取错误", "传入的字符串为空", "请重新操作");
        } else if (str.length() <= curSize) {
            return str;
        } else if (str.length() > curSize) {
            str = str.substring(1, curSize);
        }
        return str;
    }

    /**
     * 判断字符串是否超过某个长度
     * 字符串的字节长度大于判断的长度，返回true
     * 兼容中英文同时存在的字符串
     * 注：中文在oracle中占3个字节（UTF-8编码）
     *
     * @param str     需要判断的字符串
     * @param curSize 用来判断的长度
     * @return
     */
    public static Boolean checkStrByU8(String str, int curSize) {
        if (CommUtil.isEmpty(str)) {
            throw new AppException("字符串截取错误", "传入的字符串为空", "请重新操作");
        }
        Boolean over = false;
        try {
            if (str.getBytes("UTF-8").length > curSize) {
                over = true;
                return over;
            } else {
                return over;
            }
        } catch (UnsupportedEncodingException e) {
            throw new SystemException("获取字符长度失败", e, "请联系管理员");
        }
    }

    /**
     * 判断该字符是否为汉字
     * 兼容中文字符标点
     *
     * @param c
     * @return
     */
    public static final boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }

    /**
     * 数字格式化成字符，默认保留2位小数
     *
     * @param number
     * @return
     */
    public static String number2String(Number number) {
        return number2String(number, "####.##");
    }

    /**
     * 根据foramt 格式化数字
     *
     * @param number
     * @param foramt
     * @return
     */
    public static String number2String(Number number, String foramt) {
        if (isEmpty(number)) {
            throw new SystemException("数字格式化错误", "number参数不能为null", "请检查程序");
        }
        if (isEmpty(foramt)) {
            throw new SystemException("数字格式化错误", "foramt参数不能为空", "请检查程序");
        }
        DecimalFormat numberFormat = new DecimalFormat(foramt);
        return numberFormat.format(number);
    }

    /**
     * 根据#号格式化字符串
     * 例如：350213104223GB03020F00011001 "#### "   -> 3502 1310 4223 GB03 020F 0001 1001
     *
     * @param value
     * @param format
     * @return
     */
    public static String stringFormat(String value, String format) {
        final char symbol = '#';
        if (CommUtil.isEmpty(value)) {
            return "";
        }
        if (CommUtil.isEmpty(format)) {
            return value;
        }
        char[] formatChars = format.toCharArray();
        char[] valueChars = value.toCharArray();
        StringBuffer out = new StringBuffer(valueChars.length);
        for (int i = 0, j = 0; j < valueChars.length; ) {
            if (formatChars[i] == symbol) {
                out.append(valueChars[j++]);
            } else {
                out.append(formatChars[i]);
            }
            if (++i >= formatChars.length) {
                i = 0;
            }
        }
        return out.toString();
    }

    /**
     * byte转换成String
     * 字符集默认取JDK默认字符集
     *
     * @param b
     * @return
     */
    public static String byte2String(byte[] b) {
        return new String(b);
    }

    /**
     * byte转换成String
     * 字符集默认取JDK默认字符集
     *
     * @param str
     * @return
     */
    public static byte[] string2Byte(String str) {
        return CommUtil.toString(str).getBytes();
    }

    /**
     * 字号IP转换成长整型IP
     *
     * @param ip
     * @return
     */
    public static Long ipToLong(String ip) {
        String[] ips = ip.split("[.]");
        long address = 0;
        if (ips.length == 4) {
            for (int i = 0; i < ips.length; i++) {
                address = address << 8;
                address += Integer.parseInt(ips[i]);
            }
        }
        return address;
    }

    /**
     * 严格按照公安部的身份证校验规则：判断是否是有效的18位或15位个人身份证号码
     *
     * @param identityId：18位或15位个人身份证号码
     * @return：true： 有效的18位或15位个人身份证号码
     */
    public static boolean isIdentityId(String identityId) {
        if (isEmpty(identityId))
            return false;
        try {
            if (!isIdentityIdCsrq(identityId)) {
                return false;
            }

            if (identityId.length() == 18) {
                if (isLong(identityId.substring(0, 17))) {
                    String verifyCharacter = null, lastCharacter = identityId
                            .substring(17, 18);
                    verifyCharacter = getIdentityIdVerifyCharacter(identityId);// 计算１８位身份证码最后一位
                    if (equalsString(verifyCharacter, lastCharacter)) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            } else if (identityId.length() == 15) {
                try {
                    Long.parseLong(identityId);
                    return true;
                } catch (Exception ex) {
                    return false;
                }
            } else {
                return false;
            }
        } catch (Exception ex) {
            return false;
        }
    }

    /**
     * 判断身份证的日期正确
     *
     * @param identityId String
     * @return boolean
     */
    public static boolean isIdentityIdCsrq(String identityId) {
        String year = null;
        String month = null;
        String day = null;

        if (identityId.length() == 18) {
            year = identityId.substring(6, 10);
            month = identityId.substring(10, 12);
            day = identityId.substring(12, 14);
        } else if (identityId.length() == 15) {
            year = identityId.substring(6, 8);
            month = identityId.substring(8, 10);
            day = identityId.substring(10, 12);
        }
        if (year.length() == 2) {
            year = "19" + year;
        }
        String csrq = year + "-" + month + "-" + day;

        return isLegalStrDate(csrq, "yyyy-MM-dd");
    }

    /**
     * 计算１８位身份证号码最后一位的值
     *
     * @param id
     * @return
     */
    private static String getIdentityIdVerifyCharacter(String id) {
        char pszSrc[] = id.toCharArray();
        int iS = 0;
        int iW[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        char szVerCode[] = new char[]{'1', '0', 'X', '9', '8', '7', '6', '5',
                '4', '3', '2'};
        int i;
        for (i = 0; i < 17; i++) {
            iS += (int) (pszSrc[i] - '0') * iW[i];
        }
        int iY = iS % 11;
        return String.valueOf(szVerCode[iY]);
    }

    /**
     * 修补15位个人身份证号码为18位
     * 如果不是15位身份证号直接返回原值
     *
     * @param personIDCode
     * @return
     */
    public static String fixPersonIDCodeTo18(String personIDCode)
            throws SystemException {
        if (!isProbableIdentityId(personIDCode)) {
            return personIDCode;
        }

        String retIDCode = "";
        if (personIDCode == null || personIDCode.trim().length() != 15) {
            return personIDCode;
        }
        String id17 = personIDCode.substring(0, 6) + "19"
                + personIDCode.substring(6, 15); // 15为身份证补'19'

        return id17 + getIdentityIdVerifyCharacter(id17);
    }

    /**
     * 将18位个人身份证号码变为15位
     * 如果不是身份证直接返回原值
     *
     * @param personIDCode
     * @return
     */
    public static String fixPersonIDCodeTo15(String personIDCode)
            throws SystemException {
        if (!isProbableIdentityId(personIDCode)) {
            return personIDCode;
        }

        if (personIDCode.length() == 15) {
            return personIDCode;
        } else {
            return personIDCode.substring(0, 6) + personIDCode.substring(8, 17);
        }
    }

    /**
     * 大概判断是否是有效的18位或15位个人身份证号码：对于15位，必须为数字，对于18为前17为必须为数字，最后一位可能为字母，不在这两个位数的非法
     *
     * @param identityId：18位或15位个人身份证号码
     * @return：true： 有效的18位或15位个人身份证号码
     */
    public static boolean isProbableIdentityId(String identityId) {
        if (isEmpty(identityId)) {
            return false;
        }
        try {
            if (identityId.length() == 18) {
                if (isLong(identityId.substring(0, 17))) {
                    return true;
                } else {
                    return false;
                }
            } else if (identityId.length() == 15) {
                return isLong(identityId);
            } else {
                return false;
            }
        } catch (Exception ex) {
            return false;
        }
    }

    /**
     * 是否为合法的日期字符串
     *
     * @param strDate String
     * @param pattern String
     * @return boolean
     */
    public static boolean isLegalStrDate(String strDate, String pattern) {
        boolean islegal = true;
        try {
            if (strDate == null || strDate.trim().equals("")) {
                return false;
            }
            String newStrDate = date2Str(str2Date(strDate, pattern), pattern);
            if (newStrDate.equals(strDate)) {
                islegal = true;
            } else {
                islegal = false;
            }
        } catch (Exception e) {
            islegal = false;
        }
        return islegal;
    }

    /**
     * 判断Boolean对象是否为true
     *
     * @param b
     * @return
     */
    public static boolean isTrue(Boolean b) {
        if (b == null) {
            return false;
        } else {
            return b;
        }

    }


    /**
     * 统计文本区域大小
     * 统计html
     *
     * @param str
     * @param rowSize
     * @return
     */
    public static int statisticalTextAreaLengthForHtml(String str, int rowSize) {
        return statisticalTextAreaLength(str, rowSize, "2");
    }

    /**
     * 统计文本区域大小
     * 纯文本
     *
     * @param str
     * @param rowSize
     * @return
     */
    public static int statisticalTextAreaLength(String str, int rowSize) {
        return statisticalTextAreaLength(str, rowSize, "1");
    }

    /**
     * 统计文本区域大小
     *
     * @param str
     * @param rowSize
     * @return
     */
    public static int statisticalTextAreaLength(String str, int rowSize, String type) {
        if (isEmpty(str)) {
            return 0;
        }
        int row = 0;
        String[] strArray = null;
        if (CommUtil.equalsString(type, "2")) {
            strArray = str.split("<br/>");
        } else {
            strArray = str.split("\n");
        }
        //1、统计有多少主动行记录
        //2、统计每一行汉字个数和字表数字格式，字母和数字只占一半位置，超出去换一行
        int lastRowSize = 0;//最后一行支付长度
        for (String len : strArray) {
            row++;
            int number = countNumber(len);
            int letter = countLetter(len);
            int chinese = countChinese(len);
            int character = countCharacter(len);
            lastRowSize = (number + letter + character) / 2 + chinese;
            row += lastRowSize / rowSize;
        }
        return rowSize * (row - 1) + (lastRowSize % rowSize);
    }

    /**
     * 统计数字个数
     *
     * @param str
     * @return
     */
    public static int countNumber(String str) {
        int count = 0;
        Pattern p = Pattern.compile("\\d");
        Matcher m = p.matcher(str);
        while (m.find()) {
            count++;
        }
        return count;
    }

    /**
     * 统计字母个数
     *
     * @param str
     * @return
     */
    public static int countLetter(String str) {
        int count = 0;
        Pattern p = Pattern.compile("[a-zA-Z]");
        Matcher m = p.matcher(str);
        while (m.find()) {
            count++;
        }
        return count;
    }

    /**
     * 统计汉字个数
     *
     * @param str
     * @return
     */
    public static int countChinese(String str) {
        int count = 0;
        Pattern p = Pattern.compile("[\\u4e00-\\u9fa5]");
        Matcher m = p.matcher(str);
        while (m.find()) {
            count++;
        }
        return count;
    }

    /**
     * 统计特殊字符个数
     *
     * @param str
     * @return
     */
    public static int countCharacter(String str) {
        int count = 0;
        Pattern p = Pattern.compile(
                "[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]");
        Matcher m = p.matcher(str);
        while (m.find()) {
            count++;
        }
        return count;
    }

    /**
     * 对象转换成String
     * 避免String相加出现null的情况
     *
     * @param value
     * @return
     */
    public static String toString(Object value) {
        if (value == null) {
            return "";
        } else if (value instanceof String) {
            return (String) value;
        } else {
            return value.toString();
        }
    }

    /**
     * 字符串替换摸个位数的值
     *
     * @param str
     * @param n
     * @param newChar
     * @return
     */
    public static String replace(String str, int n, String newChar) {
        String str1 = "";
        String str2 = "";
        if (n > str.length()) {
            throw new SystemException("字符串替换出错", "替换的位数大于字符串的位数", "请检查检查程序");
        }
        str1 = str.substring(0, n - 1);
        str2 = str.substring(n, str.length());
        return str1 + newChar + str2;
    }

    /**
     * 数字全文检索添加百分号
     *
     * @param str
     * @return
     */
    public static String getContainsString(String str) {
        if (CommUtil.isNotEmpty(str)) {

            //替换所有特殊字符
            str = str.replace("-", "\\-");
            str = str.replace("*", "\\*");
            str = str.replace(";", "\\;");
            str = str.replace(")", "\\)");
            str = str.replace("(", "\\(");
            str = str.replace("&", "\\&");
            str = str.replace("!", "\\!");
            str = str.replace("~", "\\~");
            str = str.replace("|", "\\|");
            str = str.replace("?", "\\?");
            str = str.replace("$", "\\$");
            str = str.replace("=", "\\=");
            str = str.replace("[", "\\[");
            str = str.replace("]", "\\]");
            str = str.replace("{", "\\{");
            str = str.replace("}", "\\}");
            str = str.replace(">", "\\>");
            str = str.replace("<", "\\<");

            if (CommUtil.isNumber(str.substring(str.length() - 1))) {
                str = str + "%";
            }
        }
        return str;
    }

    /**
     * 把null转换为0长度字串
     */
    public static String null2Str(String str) {
        if (str == null || str.trim().length() == 0)
            return "";
        return str.trim();
    }

    /**
     * 取字符串的前几位
     * 最多取多少个字符
     */
    public static String maxSubstring(String str, int length) {
        if (str == null) return str;
        if (str.length() <= length) return str;
        return str.substring(0, length);
    }

    /**
     * 如果字串1是空格串或是空串，则取字串2
     */
    public static String isNulltoStr(String svalue, String newvalue) {
        String retstr = "";
        if (svalue == null || svalue.trim().equalsIgnoreCase("")) {
            retstr = newvalue;
        } else {
            retstr = svalue;
        }
        return retstr;
    }

    /**
     * 校验字符串是否在用分隔符隔开的集合中存在
     */
    public static boolean checkIsInCollection(String s, String names, String splitChar) {
        if (CommUtil.isEmpty(splitChar)) splitChar = ",";
        String objs[] = names.split(splitChar);
        for (int i = 0; i < objs.length; i++) {
            String str = objs[i];
            if (CommUtil.equalsNumberOrChar(s, objs[i])) return true;
        }
        return false;
    }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Real-IP");
//        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
//            ip = request.getHeader("Proxy-Client-IP");
//        }
//        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
//            ip = request.getHeader("WL-Proxy-Client-IP");
//        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }


    /**
     * 大写金额
     */
    public static String doubleToChinese(double num) {
        int li_amout_flag = 1;
        if (num < 0) {
            num = Math.abs(num); // 取绝对值
            li_amout_flag = -1;
        }
        String s_num, s_char, s_num_hz;
        int i_len_of_snum, i, i_flag, i_char;
        boolean flag = false;
        i_flag = 1;
        // NumberFormatter numberFormatter = new NumberFormatter();
        // s_num = numberFormatter.formatDouble(num);
        s_num = format(num, "0.00");
        if (s_num.indexOf(".") == -1) {
            s_num = s_num + ".00";
        }
        if (s_num.equals("0.00")) {
            return "零元整";
        }
        s_num_hz = "";
        i_len_of_snum = s_num.length();
        for (int k = i_len_of_snum; k > 0; k--) {
            s_char = s_num.substring(k - 1, k);
            if (s_char.equals(".")) {
                s_char = "元";
            } else {
                i_char = Integer.parseInt(s_char);
                switch (i_char) {
                    case 0:
                        s_char = "零";
                        break;
                    case 1:
                        s_char = "壹";
                        break;
                    case 2:
                        s_char = "贰";
                        break;
                    case 3:
                        s_char = "叁";
                        break;
                    case 4:
                        s_char = "肆";
                        break;
                    case 5:
                        s_char = "伍";
                        break;
                    case 6:
                        s_char = "陆";
                        break;
                    case 7:
                        s_char = "柒";
                        break;
                    case 8:
                        s_char = "捌";
                        break;
                    case 9:
                        s_char = "玖";
                }
            }

            if (!s_char.equals("零")) {
                switch (i_len_of_snum - k) {
                    case 0:
                        s_char = s_char + "分";
                        break;
                    case 1:
                        s_char = s_char + "角";
                        break;
                    case 4:
                        s_char = s_char + "拾";
                        break;
                    case 5:
                        s_char = s_char + "佰";
                        break;
                    case 6:
                        s_char = s_char + "仟";
                        break;
                    case 7:
                        s_char = s_char + "万";
                        flag = true;
                        break;
                    case 8:
                        if (i_flag == 0)
                            s_char = s_char + "拾万";
                        else
                            s_char = s_char + "拾";
                        break;
                    case 9:
                        if (i_flag == 0 && !flag) {
                            s_char = s_char + "佰万";
                            flag = true;
                            // s_char = s_char + "佰";
                        } else
                            s_char = s_char + "佰";
                        break;

                    case 10:
                        if (i_flag == 0 && !flag) {
                            s_char = s_char + "仟万";
                            flag = true;
                            // s_char = s_char + "仟";
                        } else
                            s_char = s_char + "仟";
                        break;
                    case 11:
                        s_char = s_char + "亿";
                }
                i_flag = 1;
            } else {
                i_flag = 0;
            }
            s_num_hz = s_char + s_num_hz;
        }
        i = s_num_hz.indexOf("零零");
        while (i != -1) {
            s_num_hz = s_num_hz.substring(0, i) + s_num_hz.substring(i + 1);
            i = s_num_hz.indexOf("零零");
        }
        boolean flag2 = false; // 最后一位为零
        if (s_num_hz.substring(s_num_hz.length() - 1).equals("零")) {
            if (s_num_hz.indexOf("分") != -1 || s_num_hz.indexOf("角") != -1) {
                s_num_hz = s_num_hz.substring(0, s_num_hz.length() - 1);
            } else {
                s_num_hz = s_num_hz.substring(0, s_num_hz.length() - 1); // +
                // "整";
                flag2 = true;
            }
        }
        int idx = s_num_hz.indexOf("元");
        if (s_num_hz.substring(idx - 1, idx).equals("零")) {
            s_num_hz = s_num_hz.substring(0, idx - 1) + s_num_hz.substring(idx);
        }
        if (flag2) {
            s_num_hz = s_num_hz + "整";
        }

        // 修改 0.01等小于1的金额转换不对的问题
        s_num = format(num, "0.00").substring(0, 1);
        if (s_num.equals("0") && !s_num_hz.startsWith("零")) {
            s_num_hz = "零" + s_num_hz;
        }

        if (li_amout_flag == -1) {
            s_num_hz = "负" + s_num_hz;
        }
        return s_num_hz;
    }

    /**
     * 格式化数字
     *
     * @param number
     * @param pattern
     * @return
     */
    public static String format(double number, String pattern) {
        DecimalFormat df = new DecimalFormat(pattern);
        return df.format(number);
    }

}
